﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DonutLandLibrary.Robots.Environments;
using System.Data.Entity;
using System.Data;

namespace DonutLandLibrary.Robots.Environments
{
    public class SquareCollection : IEnumerable<SquareRowCollection>, IEnumerator<SquareRowCollection>
    {
        private List<SquareRowCollection> SquareList;
        private int CurrentIndex;

        private int columnSize;
        private int rowSize;

        public int ID { get; set; }

        public int PowerSources
        {
            get
            {
                int count = 0;

                foreach (SquareRowCollection squareRowCollection in SquareList)
                {
                    count += squareRowCollection.PowerSources;
                }

                return count;
            }
        }

        public int CorrosivePatches
        {
            get
            {
                int count = 0;

                foreach (SquareRowCollection squareRowCollection in SquareList)
                {
                    count += squareRowCollection.CorrosivePatches;
                }

                return count;
            }
        }

        public SquareCollection(int columnSquareSize, int rowSquareSize)
        {
            SquareList = new List<SquareRowCollection>();

            SquareRowCollection squareRowCollection;

            columnSize = columnSquareSize;
            rowSize = rowSquareSize;

            //for each column, produce a row of squares
            for (int i = 0; i < columnSize; i++)
            {
                //create the row collection of squares, the powersources/corrsivepatches are updated by the reference values
                squareRowCollection = new SquareRowCollection(rowSize, i);

                SquareList.Add(squareRowCollection);
            }

            Reset();
        }

        public void randomlyPopulateSquares(int powerSources, int corrosivePatches, int maxPowerSourcesPerSquare)
        {
            int randomX;
            int randomY;
            int randomPowerSourceCount;
            bool randomCorrosivePatch;

            int powerSourcesLeft = powerSources;
            int corrosivePatchesLeft = corrosivePatches;

            Square randomSquare;

            RandomGenerator random = RandomGenerator.getInstance();

            while ((corrosivePatchesLeft > 0) || (powerSourcesLeft > 0))
            {
                randomX = random.RandomInt(0, rowSize -1);
                randomY = random.RandomInt(0, columnSize -1);

                randomSquare = retrieveSquareAtCoordinate(randomX, randomY);

                //cannot have corrosive patches and power source son the same square, so check that first
                if (randomSquare.CorrosivePatchPresent == false)
                {
                    randomPowerSourceCount = random.RandomInt(0, maxPowerSourcesPerSquare);

                    //makes sure that the amount of power sources for hte square does not exceed the amount left
                    if (randomPowerSourceCount > powerSourcesLeft)
                    {
                        randomPowerSourceCount = powerSourcesLeft;
                    }

                    //makes sure that the amount of power sources for the square does not exceed the maximum amount allowed for the square
                    if (randomPowerSourceCount > maxPowerSourcesPerSquare)
                    {
                        randomPowerSourceCount = maxPowerSourcesPerSquare;
                    }

                    randomSquare.PowerSources += randomPowerSourceCount;
                    powerSourcesLeft -= randomPowerSourceCount;
                }

                //Cannot have power sources and corrosive patches on the same square, so check that first
                if (randomSquare.PowerSources == 0)
                {
                    if (corrosivePatchesLeft > 0)
                    {
                        randomCorrosivePatch = random.RandomBool();

                        if ((randomCorrosivePatch) && (randomSquare.CorrosivePatchPresent != true))
                        {
                            randomSquare.CorrosivePatchPresent = true;

                            corrosivePatchesLeft -= 1;
                        }
                    }
                }
            }
        }

        public Square retrieveSquareAtCoordinate(int x, int y)
        {
            SquareRowCollection squareRowCollection;
            Square square;

            squareRowCollection = SquareList[y];

            square = squareRowCollection.retrieveSquareAtCoordinate(x);

            return square;
        }

        public Square retrieveSquareByID(int ID)
        {
            Square squareFound = null;

            Reset();

            foreach (SquareRowCollection squareRowCollection in SquareList)
            {
                squareRowCollection.Reset();

                foreach (Square square in squareRowCollection)
                {
                    if (square.ID == ID)
                    {
                        squareFound = square;

                        break;
                    }
                }

                if (squareFound != null) break;
            }

            return squareFound;
        }

        public List<Square> retrieveSquaresWithPowerSources()
        {
            List<Square> squaresFound = new List<Square>();

            Reset();

            foreach (SquareRowCollection squareRowCollection in SquareList)
            {
                squareRowCollection.Reset();

                foreach (Square square in squareRowCollection)
                {
                    if (square.PowerSources > 0)
                    {
                        squaresFound.Add(square);

                        break;
                    }
                }
            }

            return squaresFound;
        }

        public object renderSquareCollection(Square.renderFormat renderFormat)
        {
            object output = null;

            switch (renderFormat)
            {
                case Square.renderFormat.html:

                    output = renderSquareCollectionHTML();

                    break;
                case Square.renderFormat.xml:

                    throw new NotSupportedException("XML output is not currently supported");

                    //break;
                case Square.renderFormat.json:

                    throw new NotSupportedException("JSON output is not currently supported");

                    //break;

                case Square.renderFormat.data:

                    output = renderSquareCollectionData();

                    break;
            }

            return output;
        }

        private string renderSquareCollectionHTML()
        {
            StringBuilder builder = new StringBuilder();

            builder.Append("<table>");

            foreach (SquareRowCollection squareRow in SquareList)
            {
                builder.Append("<tr>");

                builder.Append(squareRow.renderSquareRow(Square.renderFormat.html));

                builder.Append("</tr>");
            }

            builder.Append("</table>");

            return builder.ToString();
        }

        private DataTable renderSquareCollectionData()
        {
            DataTable dataTable = new DataTable();

            for (int i = 0; i < rowSize; i++)
            {
                dataTable.Columns.Add(i.ToString());
            }

            foreach (SquareRowCollection squareRow in SquareList)
            {
                dataTable.Rows.Add((DataRow)squareRow.renderSquareRow(Square.renderFormat.data, dataTable));
            }

            return dataTable;
        }

        public IEnumerator<SquareRowCollection> GetEnumerator()
        {
            return this;
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public SquareRowCollection Current
        {
            get
            {
                return SquareList[CurrentIndex];
            }
        }

        public void Dispose()
        {
            //TODO : what to dispose?
        }

        object System.Collections.IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }

        public bool MoveNext()
        {
            CurrentIndex++;

            if (CurrentIndex < SquareList.Count)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public void Reset()
        {
            CurrentIndex = -1;
        }
    }
}
